home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UTracker.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  16.2 KB  |  598 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UTracker.cp 
  3. // Copyright © 1985-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UTRACKER__
  7. #include "UTracker.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. //    #ifndef __UAPPLEEVENTS__
  13. //    #include "UAppleEvents.h"
  14. //    #endif
  15.  
  16. //    #ifndef __UAPPLICATION__
  17. //    #include "UApplication.h"
  18. //    #endif
  19.  
  20. //    #ifndef __UCLIPBOARDMGR__
  21. //    #include "UClipboardMgr.h"
  22. //    #endif
  23.  
  24. //    #ifndef __UDEBUG__
  25. //    #include "UDebug.h"
  26. //    #endif
  27.  
  28. //    #ifndef __UDEPENDENCIES__
  29. //    #include "UDependencies.h"
  30. //    #endif
  31.  
  32. #ifndef __UDISPATCHER__
  33. #include "UDispatcher.h"
  34. #endif
  35.  
  36. //    #ifndef __UDOCUMENT__
  37. //    #include "UDocument.h"
  38. //    #endif
  39.  
  40. //    #ifndef __UERRORMGR__
  41. //    #include "UErrorMgr.h"
  42. //    #endif
  43.  
  44. #ifndef __UGEOMETRY__
  45. #include "UGeometry.h"
  46. #endif
  47.  
  48. #ifndef __UMACAPPGLOBALS__
  49. #include "UMacAppGlobals.h"
  50. #endif
  51.  
  52. #ifndef __UMACAPPUTILITIES__
  53. #include "UMacAppUtilities.h"
  54. #endif
  55.  
  56. #ifndef __UMEMORY__
  57. #include "UMemory.h"
  58. #endif
  59.  
  60. //    #ifndef __USCRIPTING__
  61. //    #include "UScripting.h"
  62. //    #endif
  63.  
  64. #ifndef __USCROLLER__
  65. #include "UScroller.h"
  66. #endif
  67.  
  68. #ifndef __USEGMENTS__
  69. #include "USegments.h"
  70. #endif
  71.  
  72. #ifndef __UVIEW__
  73. #include "UView.h"
  74. #endif
  75.  
  76. #ifndef __UWINDOW__
  77. #include "UWindow.h"
  78. #endif
  79.  
  80. // Toolbox
  81.  
  82. #ifndef __LOWMEM__
  83. #include <LowMem.h>
  84. #endif
  85.  
  86. #ifndef __OSEVENTS__
  87. #include <OSEvents.h>
  88. #endif
  89.  
  90. // ANSI
  91.  
  92. #ifndef __STDIO__
  93. #include <stdio.h>
  94. #endif
  95.  
  96. #ifndef __STDLIB__
  97. #include <stdlib.h>
  98. #endif
  99.  
  100. //========================================================================================
  101. // CLASS TTracker
  102. //========================================================================================
  103. #undef Inherited
  104. #define Inherited TCommand
  105.  
  106. #pragma segment MACommandNonRes
  107. MA_DEFINE_CLASS_M1(TTracker, Inherited);
  108.  
  109. //----------------------------------------------------------------------------------------
  110. // TTracker::TTracker: Empty constructor to satisfy the compiler.
  111. //----------------------------------------------------------------------------------------
  112. #pragma segment MACommandRes
  113.  
  114. TTracker::TTracker()
  115. {
  116.     fConstrainsMouse = FALSE;
  117.     fInitialPt = gZeroVPt;
  118.     fScroller = NULL;
  119.     fTrackNonMovement = FALSE;
  120.     fView = NULL;
  121.     fViewConstrain = TRUE;
  122.     fTrackPhase = trackBegin;
  123.     fAnchorPoint = gZeroVPt;
  124.     fPreviousPoint = gZeroVPt;
  125.     fNextPoint = gZeroVPt;
  126.     fLastAnchorPoint = gZeroVPt;
  127.     fLastPreviousPoint = gZeroVPt;
  128.     fLastNextPoint = gZeroVPt;
  129.     fDeskTopTrackingPort = NULL;
  130.     fHysteresis = gZeroPt;
  131.     fMovedOnce = FALSE;    
  132. } // TTracker::TTracker
  133.  
  134. //----------------------------------------------------------------------------------------
  135. // TTracker destructor
  136. //----------------------------------------------------------------------------------------
  137. #pragma segment MADestructorRes
  138.  
  139. TTracker::~TTracker()
  140. {
  141. }
  142.  
  143. //----------------------------------------------------------------------------------------
  144. // TTracker::ITracker:
  145. //----------------------------------------------------------------------------------------
  146. #pragma segment MACommandRes
  147.  
  148. void TTracker::ITracker(CommandNumber itsCommandNumber,
  149.                                TCommandHandler* itsContext,    
  150.                                Boolean canUndo,
  151.                                Boolean causesChange,
  152.                                TObject* objectToNotify,
  153.                                TView* itsView,
  154.                                TScroller* itsScroller,
  155.                                const VPoint& itsMouse)
  156. {
  157.     this->ICommand(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify);
  158.     fView = itsView;
  159.     fScroller = itsScroller;
  160.     fInitialPt = itsMouse;
  161. } // TTracker::ITracker
  162.  
  163. //----------------------------------------------------------------------------------------
  164. // TTracker::AutoScroll:
  165. //----------------------------------------------------------------------------------------
  166. #pragma segment MADoCommand
  167.  
  168. void TTracker::AutoScroll(const VPoint& delta)
  169. {
  170.     if (fScroller)
  171.         fScroller->ScrollBy(delta, kRedraw);
  172. } // TTracker::AutoScroll
  173.  
  174. //----------------------------------------------------------------------------------------
  175. // TTracker::IsDoneTracking:
  176. //----------------------------------------------------------------------------------------
  177. #pragma segment MADoCommand
  178.  
  179. Boolean TTracker::IsDoneTracking()
  180. {
  181.     if (fView)
  182.         return fView->IsDoneTracking();
  183.     else
  184.         return !StillDown();
  185. } // TTracker::IsDoneTracking
  186.  
  187. //----------------------------------------------------------------------------------------
  188. // TTracker::Process:
  189. //----------------------------------------------------------------------------------------
  190. #pragma segment MACommandRes
  191.  
  192. void TTracker::Process() // OVERRIDE
  193. {
  194. #if qDebugMsg
  195.     if (gIntenseDebugging && this)
  196.         fprintf(stderr, "Tracking Command: %s\n", this->GetClassName());
  197. #endif
  198.  
  199. #if qSegments
  200.     if (gDispatcher->fEventLevel == 1)    // Don't unload segs if in nested event handling 
  201.         UnloadAllSegments();
  202. #endif
  203.     
  204.     TTracker* finalCommand = gDispatcher->TrackMouse(fInitialPt, TEventHandler::gStdHysteresis, this);
  205.     
  206.     if (finalCommand)
  207.     {
  208.         TCommandHandler* handler = finalCommand->fContext;
  209.         if (handler)
  210.             handler->PerformCommand(finalCommand);
  211.     }
  212. } // TTracker::Process
  213.  
  214. //----------------------------------------------------------------------------------------
  215. // TTracker::TrackConstrain:
  216. //----------------------------------------------------------------------------------------
  217. #pragma segment MADoCommand
  218.  
  219. void TTracker::TrackConstrain(TrackPhase aTrackPhase,
  220.                                         const VPoint& anchorPoint,
  221.                                           const VPoint& previousPoint,
  222.                                         VPoint& nextPoint,
  223.                                         Boolean mouseDidMove)
  224. {
  225.     if (fView)
  226.         fView->TrackConstrain(aTrackPhase, anchorPoint, previousPoint, nextPoint, mouseDidMove);
  227. } // TTracker::TrackConstrain
  228.  
  229. //----------------------------------------------------------------------------------------
  230. // TTracker::TrackFeedback:
  231. //----------------------------------------------------------------------------------------
  232. #pragma segment MADoCommand
  233.  
  234. void TTracker::TrackFeedback(TrackPhase aTrackPhase,
  235.                                         const VPoint& anchorPoint,
  236.                                         const VPoint& previousPoint,
  237.                                         const VPoint& nextPoint,
  238.                                         Boolean mouseDidMove,
  239.                                         Boolean turnItOn)
  240. {
  241.     if (fView)
  242.         fView->TrackFeedback(aTrackPhase, anchorPoint, previousPoint, nextPoint, mouseDidMove, turnItOn);
  243. } // TTracker::TrackFeedback
  244.  
  245. //----------------------------------------------------------------------------------------
  246. // TTracker::TrackMouse:
  247. //----------------------------------------------------------------------------------------
  248. #pragma segment MADoCommand
  249.  
  250. TTracker* TTracker::TrackMouse(TrackPhase aTrackPhase,
  251.                                         VPoint& anchorPoint,
  252.                                         VPoint& previousPoint,
  253.                                         VPoint& nextPoint,
  254.                                         Boolean mouseDidMove)
  255. {
  256.     if (fView)
  257.         fView->TrackMouse(aTrackPhase, anchorPoint, previousPoint, nextPoint, mouseDidMove);
  258.  
  259.     if ((aTrackPhase == trackEnd) && ((fView == NULL) ||!(fView->ContainsMouse(nextPoint))))
  260.         return NULL;
  261.     else
  262.         return this;
  263. } // TTracker::TrackMouse
  264.  
  265.  
  266.  
  267. //----------------------------------------------------------------------------------------
  268. // TTracker::CleanUpFocus:
  269. //----------------------------------------------------------------------------------------
  270. #pragma segment MADoCommand
  271.  
  272. void TTracker::CleanUpFocus()
  273. {
  274.     if (fDeskTopTrackingPort)
  275.     {
  276.         SetPortWindowPort(gWorkPort);
  277.  
  278.         if (qNeedsColorQD || HasColorQD())
  279.             CloseCPort((CGrafPtr) fDeskTopTrackingPort);
  280.         else
  281.             ClosePort(fDeskTopTrackingPort);
  282.         fDeskTopTrackingPort = (GrafPtr) DisposeIfPtr((Ptr) fDeskTopTrackingPort);
  283.         fDeskTopTrackingPort = NULL;
  284.     }
  285. } // CleanUpFocus
  286.  
  287. //----------------------------------------------------------------------------------------
  288. // TTracker::DoFocus:
  289. //----------------------------------------------------------------------------------------
  290. #pragma segment MADoCommand
  291.  
  292. void TTracker::DoFocus()
  293. {
  294.     if (fView)
  295.     {
  296.         if (fDeskTopTrackingPort)
  297.             this->CleanUpFocus();
  298.  
  299.         if (!fView->Focus())
  300.         {
  301. #if qDebug
  302.             ProgramBreak("TApplication.TrackMouse: Unable to focus fView.");
  303. #endif
  304.         }
  305.     }
  306.     else
  307.     {                                            // focus on the desktop 
  308.         if (!fDeskTopTrackingPort)
  309.         {
  310.             fDeskTopTrackingPort = (GrafPtr) NewPermPtr(sizeof(CGrafPort));
  311.             if (qNeedsColorQD || HasColorQD())
  312.                 OpenCPort((CGrafPtr) fDeskTopTrackingPort);
  313.             else
  314.                 OpenPort(fDeskTopTrackingPort);
  315.         }
  316.  
  317.         CopyRgn(GetGrayRgn(), TWindow::GetVisRegion(fDeskTopTrackingPort));
  318.         fDeskTopTrackingPort->portRect = (*TWindow::GetVisRegion(fDeskTopTrackingPort))->rgnBBox;
  319.         gDispatcher->InvalidateFocus();
  320.         SetPort(fDeskTopTrackingPort);
  321.     }
  322. } // TTracker::DoFocus
  323.  
  324. //----------------------------------------------------------------------------------------
  325. // TTracker::BecomeTracker:
  326. //----------------------------------------------------------------------------------------
  327. #pragma segment MADoCommand
  328.  
  329. void TTracker::BecomeTracker(TTracker* oldTracker)
  330. {
  331.     if (oldTracker)
  332.     {
  333.         fDeskTopTrackingPort = oldTracker->fDeskTopTrackingPort;
  334.         fTrackPhase = oldTracker->fTrackPhase;
  335.  
  336.         fHysteresis = oldTracker->fHysteresis;
  337.         fTrackPhase = oldTracker->fTrackPhase;
  338.         fAnchorPoint = oldTracker->fAnchorPoint;
  339.         fPreviousPoint = oldTracker->fPreviousPoint;
  340.         fNextPoint = oldTracker->fNextPoint;
  341.         fLastAnchorPoint = oldTracker->fLastAnchorPoint;
  342.         fLastPreviousPoint = oldTracker->fLastPreviousPoint;
  343.         fLastNextPoint = oldTracker->fLastNextPoint;
  344.     }
  345.  
  346.     this->DoFocus();
  347. } // TTracker::BecomeTracker
  348.  
  349. //----------------------------------------------------------------------------------------
  350. // TTracker::ConstrainOnce:
  351. //----------------------------------------------------------------------------------------
  352. #pragma segment MADoCommand
  353.  
  354. void TTracker::ConstrainOnce(Boolean didMouseMove)
  355. {
  356.     if (this->fViewConstrain && (fView))
  357.         fNextPoint.ConstrainTo(fView->GetExtent());
  358.  
  359.     if (this->fConstrainsMouse)
  360.     {
  361.         VPoint nextPoint = fNextPoint;
  362.         this->TrackConstrain(fTrackPhase, fAnchorPoint, fPreviousPoint, nextPoint, didMouseMove);
  363.         fNextPoint = nextPoint;
  364.     }
  365. } // TTracker::ConstrainOnce
  366.  
  367. //----------------------------------------------------------------------------------------
  368. // TTracker::FeedbackOnce:
  369. //----------------------------------------------------------------------------------------
  370. #pragma segment MADoCommand
  371.  
  372. void TTracker::FeedbackOnce(Boolean mouseDidMove,
  373.                                Boolean turnItOn)
  374. {
  375.     PenNormal();
  376.     PenMode(patXor);
  377.  
  378.     if (turnItOn)
  379.     {
  380.         this->TrackFeedback(fTrackPhase, fAnchorPoint, fPreviousPoint,
  381.                             fNextPoint, mouseDidMove, turnItOn);
  382.         // save these to turn it off with
  383.         if (mouseDidMove)
  384.         {
  385.             fLastAnchorPoint = fAnchorPoint;
  386.             fLastPreviousPoint = fPreviousPoint;
  387.             fLastNextPoint = fNextPoint;
  388.         }
  389.     }
  390.     else
  391.         this->TrackFeedback(fTrackPhase, fLastAnchorPoint, fLastPreviousPoint,
  392.                             fLastNextPoint, mouseDidMove, turnItOn);
  393. } // TTracker::FeedbackOnce
  394.  
  395. //----------------------------------------------------------------------------------------
  396. // TTracker::TrackOnce:
  397. //----------------------------------------------------------------------------------------
  398. #pragma segment MADoCommand
  399.  
  400. TTracker* TTracker::TrackOnce(Boolean didMouseMove)
  401. {
  402.     TView* oldView = fView;
  403.     VPoint anchorPoint = fAnchorPoint;
  404.     VPoint previousPoint = fPreviousPoint;
  405.     VPoint nextPoint = fNextPoint;
  406.  
  407.     TTracker * newTracker = this->TrackMouse(fTrackPhase, anchorPoint, previousPoint, nextPoint, didMouseMove);
  408.     
  409.     fAnchorPoint = anchorPoint;
  410.     fPreviousPoint = previousPoint;
  411.     fNextPoint = nextPoint;
  412.     
  413.     if (newTracker == this)
  414.     {
  415.         if (this->fView != oldView)
  416.             this->BecomeTracker(this);
  417.     }
  418.     else
  419.     {
  420.         if (newTracker)
  421.             newTracker->BecomeTracker(this);
  422.         else
  423.             this->CleanUpFocus();
  424.             
  425.         // free me if a new tracker was returned
  426.         if (this->ShouldFreeOnCompletion())
  427.         {
  428.             //    // be sure to clear reference
  429.             //    if (fContext && fContext->fLastCommand == this) {
  430.             //        fContext->fLastCommand = NULL;
  431.             //    }
  432.             this->Free();
  433.         }
  434.     }
  435.  
  436.     return newTracker;
  437.     
  438. } // TTracker::TrackOnce
  439.  
  440. //----------------------------------------------------------------------------------------
  441. // TTracker::HandleTrackBegin:
  442. //----------------------------------------------------------------------------------------
  443. #pragma segment MADoCommand
  444.  
  445. TTracker* TTracker::HandleTrackBegin(const VPoint& theMouse,
  446.                                           CPoint hysteresis)
  447. {
  448.     fTrackPhase = trackBegin;
  449.  
  450.     fMovedOnce = FALSE;
  451.     fDeskTopTrackingPort = NULL;
  452.     fAnchorPoint = theMouse;
  453.     fPreviousPoint = theMouse;
  454.     fNextPoint = theMouse;
  455.     fHysteresis = hysteresis,
  456.  
  457.     this->BecomeTracker(NULL);
  458.  
  459.     this->ConstrainOnce(TRUE);
  460.     // in case Constrain changed the fNextPoint… guarantee that all 3 are the same on trackBegin
  461.     fAnchorPoint = fNextPoint;
  462.     fPreviousPoint = fNextPoint;
  463.  
  464.     TTracker* theTracker = this->TrackOnce(TRUE);
  465.     if (theTracker)
  466.     {
  467.         // in case TrackMouse changed the fNextPoint… guarantee that all 3 are the same on trackBegin
  468.         theTracker->fAnchorPoint = theTracker->fNextPoint;
  469.         theTracker->fPreviousPoint = theTracker->fNextPoint;
  470.     
  471.         theTracker->FeedbackOnce(TRUE, TRUE);
  472.     }
  473.  
  474.     return theTracker;
  475. } // TTracker::HandleTrackBegin
  476.  
  477. //----------------------------------------------------------------------------------------
  478. // TTracker::HandleTrackContinue:
  479. //----------------------------------------------------------------------------------------
  480. #pragma segment MADoCommand
  481.  
  482. TTracker* TTracker::HandleTrackContinue()
  483. {
  484.     fTrackPhase = trackContinue;                // supply trackphase to all interested parties
  485.  
  486.     this->DoFocus();
  487.  
  488.     CPoint theQDMouse;
  489.     GetMouse(theQDMouse);
  490.     if (fView)
  491.         fNextPoint = fView->QDToViewPt(theQDMouse);
  492.     else
  493.         fNextPoint = theQDMouse;
  494.  
  495.     if (!fMovedOnce)
  496.     {
  497.         this->ConstrainOnce(fPreviousPoint != fNextPoint);        // ensure that we are
  498.                                                                 // playing on a level
  499.                                                                 // field.
  500.         VPoint amtMoved = fNextPoint - fAnchorPoint;
  501.         if ((abs((int)amtMoved.h) >= fHysteresis.h) || (abs((int)amtMoved.v) >= fHysteresis.v))
  502.             fMovedOnce = TRUE;
  503.     }
  504.  
  505.     VPoint delta = gZeroVPt;
  506.     if (fMovedOnce || fTrackNonMovement)
  507.     {
  508.         if (fScroller && fView)
  509.         {
  510.             // convert fNextPoint to scroller coordinates
  511.             VPoint mouseInScroller = fNextPoint;
  512.             fView->LocalToWindow(mouseInScroller);
  513.             fScroller->WindowToLocal(mouseInScroller);
  514.  
  515.             // AutoScroll if the CPoint is outside of the scroller's extent
  516.             if (!fScroller->GetExtent().Contains(mouseInScroller))
  517.             {
  518.                 fScroller->AutoScroll(mouseInScroller, delta);// Get the amount to autoscroll
  519.                 fNextPoint += delta;
  520.             }
  521.         }
  522.  
  523.         this->ConstrainOnce(fPreviousPoint != fNextPoint);
  524.     }
  525.  
  526.     Boolean willScroll = delta != gZeroVPt;
  527.     Boolean didMove = fPreviousPoint != fNextPoint;
  528.  
  529.     this->FeedbackOnce(didMove || willScroll, FALSE);
  530.  
  531.     if (willScroll)
  532.     {
  533.         this->AutoScroll(delta);        // OK, now actually do the scrolling 
  534.         if (fView)
  535.             fView->Update();                // Keep synchronized. ScrollDraw only
  536.                                             // invalidated
  537.         this->DoFocus();                    // the focus changed 
  538.     }
  539.  
  540.     TTracker* theTracker = this->TrackOnce(didMove);
  541.     if (theTracker)
  542.     {
  543.         theTracker->FeedbackOnce(didMove || willScroll, TRUE);
  544.         theTracker->fPreviousPoint = theTracker->fNextPoint;
  545.     }
  546.  
  547.     return theTracker;
  548. } // TTracker::HandleTrackContinue
  549.  
  550. //----------------------------------------------------------------------------------------
  551. // TTracker::HandleTrackEnd:
  552. //----------------------------------------------------------------------------------------
  553. #pragma segment MADoCommand
  554.  
  555. TTracker* TTracker::HandleTrackEnd()
  556. {
  557.     fTrackPhase = trackEnd;                        // supply trackphase to all interested parties
  558.  
  559.     this->DoFocus();
  560.  
  561.     EventRecord peekEvent;
  562.  
  563.     if (!fMovedOnce)
  564.         fNextPoint = fPreviousPoint;            // normally same as original mouse down;
  565.                                                 // we don't use fAnchorPoint in case
  566.                                                 // someone has changed that -- it is more
  567.                                                 // likely that an app would change
  568.                                                 // fAnchorPoint than fPreviousPoint
  569.  
  570.     else if (OSEventAvail(mUpMask + mDownMask, &peekEvent))
  571.     {
  572.         CPoint theQDMouse = peekEvent.where;
  573.         if (fView)
  574.         {
  575.             GlobalToLocal(theQDMouse);
  576.             fNextPoint = fView->QDToViewPt(theQDMouse);
  577.         }
  578.         else
  579.             fNextPoint = theQDMouse;
  580.         this->ConstrainOnce(TRUE);
  581.     }
  582.     // else we use the last known mouse position 
  583.  
  584.     this->FeedbackOnce(TRUE, FALSE);
  585.     TTracker* theTracker = this->TrackOnce(TRUE);
  586.  
  587.     if (theTracker)
  588.         theTracker->CleanUpFocus();
  589.  
  590.     return theTracker;
  591. } // TTracker::HandleTrackEnd
  592.  
  593.  
  594. //----------------------------------------------------------------------------------------
  595. // End of UTracker.cp
  596.  
  597. #pragma segment Inline
  598.